using System;
using System.Text;

using System.Collections.Generic;
using System.Collections.Specialized;

using System.ComponentModel;

using System.Drawing.Design;

using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;


[assembly: WebResource("SBPweb.Controls.Web.Resources.clickablemenu.css", "text/css")]
[assembly: WebResource("SBPweb.Controls.Web.Resources.menujs.js", "text/javascript")]
namespace SBPweb.Controls.Web
{

	/// <summary>
	/// This class represents the design time version of the clickable menu
	/// </summary>
	public class DesignerClickableMenu : System.Web.UI.Design.ControlDesigner
	{
		/// <summary>
		/// Returns the design time html code of the control
		/// </summary>
		/// <returns>string</returns>
		public override string GetDesignTimeHtml()
		{
			return "<span>Clickable Menu</span>";
		}
	}

	/// <summary>
	/// This class implements a clickable menu control
	/// </summary>
	[Designer(typeof(DesignerClickableMenu))]
	[Description("Javascript base Click - driven Menu")]
	[DefaultProperty("SiteMapPath")]
	[ToolboxData("<{0}:ClickableMenu runat=server></{0}:ClickableMenu>")]
	public class ClickableMenu : WebControl
    {

        #region Classes

		/// <summary>
		/// Describes a clicakble menu item
		/// </summary>
        public class ClickableMenuItem
        {
			/// <summary>
			/// Title of menu item
			/// </summary>
            public string title;
			/// <summary>
			/// Depth of menu item
			/// </summary>
            public int depth;
			/// <summary>
			/// URL of menu item
			/// </summary>
            public string url;
			/// <summary>
			/// Returns true, if the menu item has a children
			/// </summary>
            public bool hasChildren;
			/// <summary>
			/// Id of the parent of the menu item
			/// </summary>
            public string parentId;
			/// <summary>
			/// Id of the child client of the menu item
			/// </summary>
            public string childClientId;
			/// <summary>
			/// Returns true if the menu item is enabled
			/// </summary>
            public bool isEnabled;
        }

        #endregion

        #region Private members

        private List<ClickableMenuItem> mClickableMenuItems = new List<ClickableMenuItem>();
        private List<ClickableMenuItem> mAllowedMenuItems = new List<ClickableMenuItem>();

        #endregion

        #region Private properties 

        private XmlSiteMapProvider XmlSiteMap
        {
            get
            {
                XmlSiteMapProvider xmlSiteMap = new XmlSiteMapProvider();
                NameValueCollection myCollection = new NameValueCollection(1);
                myCollection.Add("siteMapFile", SiteMapPath);
                xmlSiteMap.Initialize("provider", myCollection);
                xmlSiteMap.BuildSiteMap();
                SiteMapDataSource siteMap = new SiteMapDataSource();
                siteMap.Provider = xmlSiteMap;
                siteMap.ShowStartingNode = false;
                return xmlSiteMap;
            }
        }

        #endregion

		#region Public Properties

		/// <summary>
		/// Gets or sets sitemap path data in the view state of the control
		/// </summary>
		[Bindable(true)]
		[Category("Data")]
		[DefaultValue("")]
		[Localizable(true)]
		[UrlProperty()]
		public string SiteMapPath
		{
			get
			{
				String s = (String)ViewState["SiteMapPath"];
				return ((s == null) ? String.Empty : s);
			}

			set
			{
				ViewState["SiteMapPath"] = value;
			}
		}

		/// <summary>
		/// Gets or sets background image url in the view state of the control
		/// </summary>
		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("")]
		[Localizable(true)]
		[UrlProperty()]
		public string BackGroundImageURL
		{
			get
			{
				String s = (String)ViewState["BackGroundImageURL"];
				return ((s == null) ? String.Empty : s);
			}

			set
			{
				ViewState["BackGroundImageURL"] = value;
			}
		}

		/// <summary>
		/// Gets or sets submenu image url in the view state of the control
		/// </summary>
		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("")]
		[Localizable(true)]
		[UrlProperty()]
		public string SubMenuImageURL
		{
			get
			{
				String s = (String)ViewState["SubMenuImageURL"];
				return ((s == null) ? String.Empty : s);
			}

			set
			{
				ViewState["SubMenuImageURL"] = value;
			}
		}

		/// <summary>
		/// Gets or sets main menu image url in the view state of the control
		/// </summary>
		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("")]
		[Localizable(true)]
		[UrlProperty()]
		public string MainMenuImageURL
		{
			get
			{
				String s = (String)ViewState["MainMenuImageURL"];
				return ((s == null) ? String.Empty : s);
			}

			set
			{
				ViewState["MainMenuImageURL"] = value;
			}
		}

		/// <summary>
		/// Gets or sets main menu itmes css class in the view state of the control
		/// </summary>
		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("")]
		[Localizable(false)]
		public string MainMenuItemsCssClass
		{
			get
			{
				String s = (String)ViewState["MainMenuItemsCssClass"];
				return ((s == null) ? String.Empty : s);
			}

			set
			{
				ViewState["MainMenuItemsCssClass"] = value;
			}
		}

		/// <summary>
		/// Gets or sets sub menu items css class in the view state of the control
		/// </summary>
		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("")]
		[Localizable(false)]
		public string SubMenuItemsCssClass
		{
			get
			{
				String s = (String)ViewState["SubMenuItemsCssClass"];
				return ((s == null) ? String.Empty : s);
			}

			set
			{
				ViewState["SubMenuItemsCssClass"] = value;
			}
		}

		/// <summary>
		/// Gets or sets css class of submenu items with subnodes in the view state of the control
		/// </summary>
		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("")]
		[Localizable(false)]
		public string SubMenuItemsWithSubNodesCssClass
		{
			get
			{
				String s = (String)ViewState["SubMenuItemWithSubNodesCssClass"];
				return ((s == null) ? String.Empty : s);
			}

			set
			{
				ViewState["SubMenuItemWithSubNodesCssClass"] = value;
			}
		}

		#endregion

		#region Private methods

		private Control FindControlRecursively(string id, Control ct)
		{
			if (ct == null)
			{
				return null;
			}

			if (ct.ID == id)
			{
				return ct;
			}
			else
			{
				if (ct.HasControls())
				{
					Control c;
					foreach (Control ctl in ct.Controls)
					{
						if ((c = FindControlRecursively(id, ctl)) != null)
							return c;
					}
				}
				return null;
			}
		}

		private void GetSiteMapNodes(SiteMapNode root, int depth)
		{
			foreach (SiteMapNode node in root.ChildNodes)
			{
				ClickableMenuItem menuItem = new ClickableMenuItem();
				menuItem.title = node.Title;
				menuItem.depth = depth;
				menuItem.url = node.Url;
				menuItem.hasChildren = node.HasChildNodes;
				if (depth != 0)
				{
					menuItem.parentId = node.ParentNode.Title;
				}
				else
				{
					menuItem.parentId = "";
				}
				mClickableMenuItems.Add(menuItem);
				if (node.HasChildNodes)
				{
					GetSiteMapNodes(node, depth + 1);
				}
			}
		}

		private static void ClearControls(Control control)
		{
			if (control.Controls.Count != 0)
			{
				foreach (Control c in control.Controls)
				{
					ClearControls(c);
				}
				control.Controls.Clear();
			}
		}

		private void RenderMenu()
		{
			HtmlTable mainTable = new HtmlTable();
			mainTable.CellPadding = 0;
			mainTable.CellSpacing = 0;
			HtmlTableRow mainTr = new HtmlTableRow();
			mainTable.Rows.Add(mainTr);
			HtmlGenericControl mainDiv = new HtmlGenericControl("div");

			Controls.Add(mainTable);
			Controls.Add(mainDiv);

			XmlSiteMapProvider xmlSiteMap = XmlSiteMap;
			GetSiteMapNodes(xmlSiteMap.RootNode, 0);

			for (int i = 0; i < mClickableMenuItems.Count; i++)
			{
				ClickableMenuItem c = mClickableMenuItems[i];
				c.isEnabled = true;
				mAllowedMenuItems.Add(c);
			}

			for (int i = 0; i < mAllowedMenuItems.Count; i++)
			{
				//Mainmenu nodes
				if (mAllowedMenuItems[i].depth == 0)
				{
					HtmlTableCell td = new HtmlTableCell();
					td.Attributes["class"] = "mainMenuTd";
					td.Attributes["onmouseover"] = "mouseOver(this, '" + mAllowedMenuItems[i].title + "');";
					td.Attributes["onmouseleave"] = "mouseLeave(this, '" + mAllowedMenuItems[i].title + "');";
					td.Attributes["onmouseout"] = "mouseLeave(this, '" + mAllowedMenuItems[i].title + "');";

					if (mAllowedMenuItems[i].hasChildren)
					{
						//For more place...
						HtmlTableCell emptyTd = new HtmlTableCell();
						HtmlGenericControl emptyDiv = new HtmlGenericControl("div");
						emptyDiv.InnerHtml = "<div class='emptyDiv'></div>";
						emptyTd.Controls.Add(emptyDiv);
						mainTr.Controls.Add(emptyTd);

						//Create new main menu node
						HtmlTable childTable = new HtmlTable();
						childTable.Attributes["width"] = "100%";
						childTable.Attributes["cellpadding"] = "0";
						childTable.Attributes["cellspacing"] = "0";
						childTable.Attributes["onclick"] = String.Format("setLyrOfMenu(this,'{0}');", mAllowedMenuItems[i].title);
						childTable.ID = mAllowedMenuItems[i].title;

						td.Controls.Add(childTable);

						HtmlTableRow childRow = new HtmlTableRow();
						childTable.Rows.Add(childRow);

						HtmlTableCell childCellForLink = new HtmlTableCell();
						childCellForLink.Attributes["class"] = "linkOfTdWithChild";
						HtmlTableCell childCellForImage = new HtmlTableCell();
						childCellForImage.Attributes["class"] = "imageOfTdWithChild";
						childCellForImage.Attributes["align"] = "right";
						childRow.Cells.Add(childCellForLink);
						childRow.Cells.Add(childCellForImage);

						mainTr.Controls.Add(td);

						childCellForLink.InnerHtml = String.Format("<span class='menuLink'>&nbsp;{0}&nbsp;</span>", mAllowedMenuItems[i].title);
						childCellForImage.InnerHtml = String.Format("<img class='menuImg' src='{0}'></img>", MainMenuImageURL);

						//Div and table for child menus
						HtmlGenericControl div = new HtmlGenericControl("div");

						div.ID = String.Format("div{0}", mAllowedMenuItems[i].title);
						div.Attributes["class"] = "selectfree";
						div.Style["display"] = "none";

						HtmlImage bgImage = new HtmlImage();
						bgImage.ID = String.Format("bcImg{0}", mAllowedMenuItems[i].title);
						bgImage.Attributes["class"] = "menuBg";
						bgImage.Src = BackGroundImageURL;

						HtmlTable table = new HtmlTable();
						table.Attributes["class"] = "menuTable";
						table.ID = String.Format("table{0}", mAllowedMenuItems[i].title);

						div.Controls.Add(bgImage);
						div.Controls.Add(table);

						if (Page.Request.Browser.Browser == "IE" && Convert.ToDouble(Page.Request.Browser.Version, System.Globalization.NumberFormatInfo.InvariantInfo) <= 6.5)
						{
							HtmlGenericControl iframe = new HtmlGenericControl("iframe");
							iframe.Attributes["src"] = String.Format("{0}/Pages/Blank.htm", Page.Request.ApplicationPath);
							div.Controls.Add(iframe);
						}

						mainDiv.Controls.Add(div);

						mAllowedMenuItems[i].childClientId = div.ClientID;

						div.Attributes["onmouseenter"] = "enterToTheDiv(this);";
						div.Attributes["onmouseleave"] = "hideDiv(this);";
						div.Attributes["onmouseover"] = "enterToTheDivFF(event, this)";
						div.Attributes["onmouseout"] = "hideDivForFF(event, this);";
					}
					// If there aren't child nodes
					else
					{
						//menuTr.Controls.Add(td);
						td.Style["cursor"] = "pointer";
						td.InnerHtml = String.Format("<a style='text-decoration:none;' href=\"{0}\" onclick=\"return beforeSubmit()\">{1}</a>", mAllowedMenuItems[i].url, mAllowedMenuItems[i].title);

						mAllowedMenuItems[i].childClientId = "";
					}
				}
				//Submenu nodes
				else
				{
					if (mAllowedMenuItems[i].hasChildren)
					{
						HtmlTable table = (HtmlTable)FindControlRecursively(String.Format("table{0}", mAllowedMenuItems[i].parentId), this);
						HtmlTableRow tr = new HtmlTableRow();
						table.Rows.Add(tr);
						HtmlTableCell td = new HtmlTableCell();
						tr.Cells.Add(td);
						td.Attributes["class"] = "mainMenuTd";
						td.Attributes["onmouseover"] = "mouseOver(this, '" + mAllowedMenuItems[i].title + "');";
						td.Attributes["onmouseleave"] = "mouseLeave(this, '" + mAllowedMenuItems[i].title + "');";
						td.Attributes["onmouseout"] = "mouseLeave(this, '" + mAllowedMenuItems[i].title + "');";

						HtmlTable childTable = new HtmlTable();
						childTable.Attributes["width"] = "100%";
						childTable.Attributes["cellpadding"] = "0";
						childTable.Attributes["cellspacing"] = "0";
						childTable.Attributes["onclick"] = String.Format("setLyrOfSubMenu(this,'{0}')", mAllowedMenuItems[i].title);
						childTable.ID = mAllowedMenuItems[i].title;
						td.Controls.Add(childTable);

						HtmlTableRow childRow = new HtmlTableRow();
						childTable.Rows.Add(childRow);
						HtmlTableCell childCellForLink = new HtmlTableCell();
						childCellForLink.Attributes["class"] = "linkOfTdWithChild";
						childRow.Cells.Add(childCellForLink);
						HtmlTableCell childCellForImage = new HtmlTableCell();
						childCellForImage.Attributes["class"] = "imageOfTdWithChlid";
						childRow.Cells.Add(childCellForImage);

						childCellForLink.InnerHtml = String.Format("<span class='menuLink'>&nbsp;{0}&nbsp;</span>", mAllowedMenuItems[i].title);
						childCellForImage.Attributes["align"] = "right";
						childCellForImage.InnerHtml = String.Format("<img class='menuImg' src='{0}'></img>", SubMenuImageURL);

						//Div and table for child menus
						HtmlGenericControl div = new HtmlGenericControl("div");
						div.ID = "div" + mAllowedMenuItems[i].title;
						div.Attributes["class"] = "selectfree";
						div.Style["display"] = "none";

						HtmlImage bgImage = new HtmlImage();
						bgImage.ID = String.Format("bcImg{0}", mAllowedMenuItems[i].title);
						bgImage.Attributes["class"] = "menuBg";
						bgImage.Src = BackGroundImageURL;

						table = new HtmlTable();
						table.Attributes["class"] = "menuTable";
						table.ID = "table" + mAllowedMenuItems[i].title;

						div.Controls.Add(bgImage);
						div.Controls.Add(table);

						if (this.Page.Request.Browser.Browser == "IE" && Convert.ToDouble(this.Page.Request.Browser.Version, System.Globalization.NumberFormatInfo.InvariantInfo) <= 6.5)
						{
							HtmlGenericControl iframe = new HtmlGenericControl("iframe");
							iframe.Attributes["src"] = String.Format("{0}/Pages/Blank.htm", Page.Request.ApplicationPath);
							div.Controls.Add(iframe);
						}

						mainDiv.Controls.Add(div);

						mAllowedMenuItems[i].childClientId = div.ClientID;

						div.Attributes["onmouseenter"] = "enterToTheDiv(this);";
						div.Attributes["onmouseleave"] = "hideDiv(this);";
						div.Attributes["onmouseover"] = "enterToTheDivFF(event, this)";
						div.Attributes["onmouseout"] = "hideDivForFF(event, this);";
					}
					else
					{
						if (mAllowedMenuItems[i].isEnabled)
						{
							HtmlTable table = (HtmlTable)FindControlRecursively(String.Format("table{0}", mAllowedMenuItems[i].parentId), this);
							HtmlTableRow tr = new HtmlTableRow();
							table.Rows.Add(tr);
							HtmlTableCell td = new HtmlTableCell();
							tr.Cells.Add(td);

							td.InnerHtml = String.Format("<a style='text-decoration:none; display:block; width:100%;' href=\"{0}\" onclick=\"return beforeSubmit()\">&nbsp;{1}</a>", mAllowedMenuItems[i].url, mAllowedMenuItems[i].title);
							td.Attributes["class"] = "mainMenuTd";
							td.Style["cursor"] = "pointer";
							td.Attributes["onmouseover"] = "mouseOver(this, '" + mAllowedMenuItems[i].title + "');";
							td.Attributes["onmouseleave"] = "mouseLeave(this, '" + mAllowedMenuItems[i].title + "');";
							td.Attributes["onmouseout"] = "mouseLeave(this, '" + mAllowedMenuItems[i].title + "');";
							td.Attributes["onclick"] = String.Format("tdClick(event, this, '{0}')", mAllowedMenuItems[i].url);

							mAllowedMenuItems[i].childClientId = "";
						}
						else
						{
							HtmlTable table = (HtmlTable)FindControlRecursively(String.Format("table{0}", mAllowedMenuItems[i].parentId), this);
							HtmlTableRow tr = new HtmlTableRow();
							table.Rows.Add(tr);
							HtmlTableCell td = new HtmlTableCell();
							tr.Cells.Add(td);
							td.InnerHtml = String.Format("<span class='disableMenuLink'>&nbsp;{0}&nbsp;</span>", mAllowedMenuItems[i].title);
							td.Attributes["class"] = "mainMenuTd";
							td.Attributes["onmouseover"] = "mouseOver(this, '" + mAllowedMenuItems[i].title + "');";
							td.Attributes["onmouseleave"] = "mouseLeave(this, '" + mAllowedMenuItems[i].title + "');";
							td.Attributes["onmouseout"] = "mouseLeave(this, '" + mAllowedMenuItems[i].title + "');";

							mAllowedMenuItems[i].childClientId = "";
						}
					}
				}
			}
		}

		/// <summary>
		/// Returns the menu nodes
		/// </summary>
		/// <returns></returns>
		private string GetAllowedNodes()
		{
			StringBuilder sb = new StringBuilder(@"menuNodes = new Array();");
			for (int i = 0; i < mAllowedMenuItems.Count; ++i)
			{
				sb.Append(String.Format("node = new MenuNode('{0}','{1}','{2}','{3}','{4}', '{5}');menuNodes[menuNodes.length] = node;", mAllowedMenuItems[i].title, mAllowedMenuItems[i].depth, mAllowedMenuItems[i].url, mAllowedMenuItems[i].hasChildren, mAllowedMenuItems[i].parentId, mAllowedMenuItems[i].childClientId));
			}
			return sb.ToString();
		}

		#endregion

		#region Overrided Members

		/// <summary>
		/// This method preforms pre render operations
		/// </summary>
		/// <param name="e">EventArgs e</param>
		protected override void OnPreRender(EventArgs e)
		{
			RenderMenu();

			// add style sheet
			HtmlLink cssLink = new HtmlLink();
			cssLink.Href = Page.ClientScript.GetWebResourceUrl(this.GetType(), "SBPweb.Controls.Web.Resources.clickablemenu.css");
			cssLink.Attributes.Add("rel", "stylesheet");
			cssLink.Attributes.Add("type", "text/css");
			this.Page.Header.Controls.Add(cssLink);

			// add static js library (can be cached by browsers)
			Page.ClientScript.RegisterClientScriptInclude
			(
				"MenuJs",
				Page.ClientScript.GetWebResourceUrl
				(
					this.GetType(), "SBPweb.Controls.Web.Resources.menujs.js"
				)
			);

			// add dynamic js library
			Page.ClientScript.RegisterClientScriptBlock
			(
				this.GetType(),
				"dynamicMenuJsPart",
				"<script type=\"text/javascript\" language=\"javascript\">" + GetAllowedNodes() + "</script>"
			);
			base.OnPreRender(e);
		}

		/// <summary>
		/// Gets design time data for a control
		/// </summary>
		/// <returns>A System.Collections.IDictionary containing the design-time data for the control</returns>
		protected override System.Collections.IDictionary GetDesignModeState()
		{
			return base.GetDesignModeState();
		}

		/// <summary>
		/// Sets design-time data for a control.
		/// </summary>
		/// <param name="data">A System.Collections.IDictionary containing the design-time data for the control.</param>
		protected override void SetDesignModeState(System.Collections.IDictionary data)
		{
			base.SetDesignModeState(data);
		}

		#endregion

	}
}
